<template>
<div class="row">
  <my-add-ip-detail></my-add-ip-detail>
  <div class="col-md-12">
    <my-navbar fixed="top">
      <template slot="left">
        <select class="form-control" v-model="moduleIndex" @change.prevent="onModuleChange">
          <option v-for="option in moduleOptions" :value="$index">{{option.text}}</option>
        </select>             
        <button class="btn btn-default" @click.prevent="onScan">
          <span class="glyphicon glyphicon-plus"></span> {{$t("common.scan")}}
        </button>
        <select class="form-control" v-model="cmdName">
          <option v-for="option in cmdOptions">{{option.name}}</option>
        </select> 
        <button class="btn btn-default" @click.prevent="onBatchExe">
          {{$t("webapp.batchExe")}}
        </button>     
      </template>
    </my-navbar>
  </div>
  <div class="col-md-12">
    <my-table :cfg="cfg" :list="orderList" :loading="false"></my-table>
  </div>
</div>
</template>

<script>
import _ from 'lodash'
import async from 'async'
import ebus from 'libs/ebus.js'
import toast from 'libs/toast.js'
import locales from './locales.js'
import msgbox from 'libs/msgbox.js'
import {http} from 'share/common/api.js'
import cmds from './cmds.js'

export default {
  locales,
  data () {
    return {
      scanDevCnt: 0,
      cmdName: '',
      moduleIndex: 0,
      moduleOptions: [{
        scanPort: 8080,
        text: 'FOUNDER-100E/D/ES/DS',
        test: /^codec\.founder100/,
        services: [{
          name: 'platform',
          port: 8080
        }, {
          name: 'codec',
          port: 7080
        }]
      }, {
        scanPort: 9080,
        text: 'M-CT-SERVER',
        test: /^server\.main\.pc/,
        services: [{
          name: 'ct-server',
          port: 9080
        }]
      }, {
        scanPort: 6080,
        text: 'M-MD-SERVER',
        test: /^server\.media\.pc/,
        services: [{
          name: 'md-server',
          port: 6080
        }]
      }],
      cfg: {
        checkable: true,
        showHead: true,
        columns: [{
          field: 'ipaddr',
          width: '10%',
          name: 'IP'
        }, {
          field: 'devModel',
          width: '10%',
          name: 'DevModel'        
        }, {
          field: 'softwareVersion',
          width: '10%',
          name: 'Version'        
        }, {
          field: 'result',
          width: 'auto',
          name: 'Result'        
        }]
      },
      list: []
    }
  },
  computed: {
    orderList () {
      return _.orderBy(this.list, ['ipaddr'], ['asc'])
    },
    cmdOptions () {
      let module = this.moduleOptions[this.moduleIndex]
      return _.filter(cmds, function(cmd) {
        return this.getServiceWithCmd(module, cmd) != null
      }.bind(this))
    }
  },
  methods: {
    getServiceWithCmd (module, cmd) {
      return _.find(module.services, (service) => {
        return cmd.service.includes(service.name)
      })
    }, 
    onModuleChange () {
      this.list.splice(0, this.list.length)
      this.cmdName = ''
    },
    onScan () {
      ebus.emit('show-add-ip-detail')
    },
    stepLogin (host, cmd, dev, cb) {
      http(host, '/api/auth/login', 'POST', {
        username: 'api',
        password: 'api'
      }).then(function(res) {
        if (res && res.data && res.data.code === 0) {
          cb(null, host, cmd, dev)
        } else {
          dev.result = `code[${res.data.code}]`
          cb({msg: `code[${res.data.code}]`})
        }
      }, function(res) {
        dev.result = 'no response'
        cb({msg: 'error'})
      })
    }, 
    stepExeCmd (host, cmd, dev, cb) {
      http(host, cmd.URI, 'POST', cmd.body).then(function(res) {
        if (res && res.data && res.data.code === 0) {
          dev.result = res.data.data.result
          cb(null)
        } else {
          dev.result = `code[${res.data.code}]`
          cb({msg: `code[${res.data.code}]`})
        }
      }, function(res) {
        dev.result = 'no response'
        cb({msg: 'error'})
      })
    },   
    exeCmd (dev, service, cmd, callback) {
      let host = `http://${dev.ipaddr}:${service.port}`

      async.waterfall([
        function(cb) {
          cb(null, host, cmd, dev)      
        }, 
        this.stepLogin,
        this.stepExeCmd
        ], 
        function (err, result) {
          callback()
        }
      )
    },
    onBatchExe () {
      var devs = _.filter(this.list, {_checked: true})
      if (devs.length <= 0) {
        toast.e(this, this.$t('common.fail'), this.$t('error.unselected'))
        return
      }
      let cmd = _.find(cmds, {name: this.cmdName})
      if (!cmd) {
        toast.e(this, this.$t('common.fail'), this.$t('error.unselected'))
        return
      }
      _.forEach(devs, (item) => {
        item.result = ''
      })
      let module = this.moduleOptions[this.moduleIndex]
      let service = this.getServiceWithCmd(module, cmd)
      async.eachLimit(devs, 15, function(dev, callback) {
        this.exeCmd(dev, service, cmd, callback)
      }.bind(this), function(err) {
      })
    },
    scanDev (ipaddr, callback) {
      let module = this.moduleOptions[this.moduleIndex]
      let host = `http://${ipaddr}:${module.scanPort}`
      let test = module.test

      http(host, '/api/platform/cfg', 'GET', null, {timeout: 1000})
      .then(function(res) {
        if (res && res.data && res.data.code === 0) {
          let platformInfo = res.data.data
          if (test.test(platformInfo.devModel)) {
            this.list.push({
              ipaddr: ipaddr,
              devModel: platformInfo.devModel,
              softwareVersion: platformInfo.softwareVersion,
              result: '',
              _checked: false
            }) 
            this.scanDevCnt++         
          }
        }
        callback()
      }.bind(this), function(res) {
        callback()
      })
    },
    onAddIp (ipList) {
      if (ipList.length > 15) {
        msgbox.showWait(this.$t('alert.plzWait'), this.$t('common.processing'), -1)
      }
      this.scanDevCnt = 0
      async.eachLimit(ipList, 15, function(item, callback) {
        let dev = _.find(this.list, {ipaddr: item})
        if (dev) {
          callback()
          return
        }
        this.scanDev(item, callback)
      }.bind(this), function(err) {
        if (ipList.length > 15) {
          msgbox.close()
        }
        if (this.scanDevCnt > 0) {
          toast.s(this, this.$t('common.finish'), this.$t('alert.findResult', {cnt: this.scanDevCnt}))
        } else {
          toast.w(this, this.$t('common.finish'), this.$t('error.notFound'))
        }
      }.bind(this))
    }
  },
  ready () {
    ebus.on('add-ip', this.onAddIp)
  }
}
</script>

<style>
body { 
  padding-top: 70px; 
}
</style>